<template>
  <el-card shadow="never">
    <template #header>
      <el-form label-width="80px">
        <el-row :gutter="10">
          <el-col :span="6" :xs="24">
            <el-form-item label="菜单名称">
              <el-input v-model="page.name"/>
            </el-form-item>
          </el-col>
          <el-col :span="6" :xs="24">
            <el-form-item label="url">
              <el-input v-model="page.url"/>
            </el-form-item>
          </el-col>
          <el-col :span="6" :xs="24">
            <el-form-item label-width="20px">
              <el-button type="primary" @click="getMenuData">查询</el-button>
              <el-button @click="resetSearch">重置</el-button>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
    </template>
    <div style="text-align: right;margin-bottom: 10px">
      <el-button type="primary" icon="el-icon-plus" v-permiss="['insert']" @click="addMenu()">添加目录</el-button>
    </div>
    <Table rowKey="id" :tableColumn="tableColumn" ref="tableRef" border lazy :treeLoad="treeLoad" :tableData="tableData"
           :page="false"
    >
      <template #type="{row}">
        {{ menuType.find(item => item.value === row.type).label }}
      </template>
      <template #icon="{row}">
        <i :class="row.icon"></i>
      </template>
      <template #status="{row}">
        <el-switch :model-value="row.status === 1" @change="changeStatus(row)"></el-switch>
      </template>
      <template #handle="{row}">
        <el-button type="text" @click="addMenu(row)">添加下级</el-button>
        <el-button type="text" @click="editMenu(row)">编辑</el-button>
        <el-button type="text" @click="edlMenu(row)">删除</el-button>
      </template>
    </Table>
    <Dialog v-model="visible.isShow"
            :title="visible.title"
            @close="clearForm"
            @cancel="visible.isShow = false"
            @confirm="menuConfirm"
    >

      <el-form label-width="100px" ref="menuRef" :model="menuForm" :rules="rulesMenuForm">
        <el-form-item label="菜单名称" prop="name">
          <el-input v-model="menuForm.name"/>
        </el-form-item>
        <el-form-item label="菜单类型" prop="type" v-if="isAddLower">
          <el-radio-group v-model="menuForm.type">
            <el-radio v-for="item in menuType" :label="item.value" :key="item.value">{{ item.label }}</el-radio>
          </el-radio-group>
        </el-form-item>
        <!--        <el-form-item label="父级" v-if="visible.type ==='edit'">-->
        <!--          <el-cascader-->
        <!--              style="width: 100%"-->
        <!--              v-model="menuForm.parentId"-->
        <!--              @change="checkChange"-->
        <!--              :options="cascaderData"-->
        <!--              :props="{ checkStrictly: true,label:'name',value:'id' }"-->
        <!--              clearable></el-cascader>-->
        <!--        </el-form-item>-->
        <el-form-item label="请求地址" prop="url" v-if="menuForm.type !== 0">
          <el-input v-model="menuForm.url"/>
        </el-form-item>
        <el-form-item label="权限标识" prop="perms" v-if="menuForm.type === 2">
          <el-input v-model="menuForm.perms"/>
        </el-form-item>
        <el-form-item label="前端Name" prop="webUrl">
          <el-input v-model="menuForm.webUrl"/>
        </el-form-item>
        <el-form-item label="菜单icon" prop="icon">
          <el-input v-model="menuForm.icon"/>
        </el-form-item>
        <el-form-item label="排序">
          <el-input-number v-model="menuForm.orderNum"/>
        </el-form-item>
      </el-form>
    </Dialog>
  </el-card>
</template>

<script>
import {defineComponent, onMounted, reactive, ref, toRefs,} from 'vue'
import {fetchMenuList, insertMenu, updateMenu, changeMenuStatus, deleteMenu} from '@/api'
import Dialog from "@/components/Dialog";
import {ElMessage, ElMessageBox} from "element-plus";

const tableColumn = [
  {label: '菜单名称', prop: 'name', minWidth: 200},
  {label: '权限标识', prop: 'perms', align: 'center'},
  {label: '编号', prop: 'id', align: 'center'},
  {label: '图标', prop: 'icon', slot: 'icon', align: 'center'},
  {label: '排序', prop: 'orderNum', align: 'center'},
  {label: '状态', prop: 'status', slot: 'status', align: 'center'},
  {label: '类型', prop: 'type', slot: 'type', align: 'center'},
  {label: 'URL地址', prop: 'url', align: 'center', minWidth: 150},
  {label: '前端Name', prop: 'webUrl', align: 'center', minWidth: 100},
  {label: '操作', slot: 'handle', prop: 'handle', fixed: 'right', minWidth: 150, align: 'center'},
]
const menuType = [
  {label: '目录', value: 0},
  {label: '菜单', value: 1,},
  {label: '按钮', value: 2,},
]
export default defineComponent({
  name: "MenuManage",
  components: {Dialog},
  setup() {
    const menuRef = ref(null)
    const tableRef = ref(null)
    const state = reactive({
      page: {
        pageNum: 1,
        pageSize: 10,
        total: 0
      },
      visible: {
        isShow: false,
        type: 'add',
        title: ''
      },
      rulesMenuForm: {
        name: [
          {required: true, message: '不能为空', trigger: 'blur'}
        ],
        url: [
          {required: true, message: '不能为空', trigger: 'blur'}
        ],
        // webUrl: [
        //   {required: true, message: '不能为空', trigger: 'blur'}
        // ],
      },
      menuForm: {
        type: 0,
        parentId: 0
      },
      tableData: [],
      cascaderData: [],
      isAddLower: false,
      tableAllData: [],
      lazyReloveMap: new Map(),
      parentId: null
    })
    const methods = reactive({
      getMenuData: async () => {
        const res = await fetchMenuList(state.page)
        if (res.code === 200) {
          const data = [...res.data].filter(i => i.parentId === 0).map(item => {
            if (item.type === 0 || item.type === 1) item.hasChildren = true
            return item
          })
          state.tableAllData = res.data
          state.tableData = methods.formatTree(data).sort((a, b) => a.orderNum - b.orderNum)
          console.log(state.tableData)
          // if (state.parentId !== null) {
          //   methods.setUpDateTree()
          // }
        }
      },
      setUpDateTree() {
        if (state.lazyReloveMap.size !== 0) {
          const key = state.isAddLower ? state.menuForm.parentId : state.parentId
          const {tree, treeNode, resolve} = state.lazyReloveMap.get(state.parentId)
          tableRef.value.$refs.table.store.states.lazyTreeNodeMap.value[key] = []
          // 将数据缓存设置空
          methods.treeLoad(tree, treeNode, resolve)
        }
      },
      treeLoad(tree, treeNode, resolve) {
        // 过滤该菜单是否有子级
        state.lazyReloveMap.set(tree.id, {tree, treeNode, resolve})
        const list = state.tableAllData.filter(child => tree.id === child.parentId).map(i => {
          // 查询菜单是否有子级权限
          const childArr = state.tableAllData.filter(val => val.parentId === i.id)
          // 如果有子级添加 hasChildren
          if (childArr.length && childArr.length !== 0) i.hasChildren = true
          return i
        }).sort((a, b) => {
          return a.orderNum - b.orderNum
        })
        resolve(list)
      },
      // 重置
      resetSearch: () => {
        state.page = {
          pageNum: 1,
          pageSize: 10,
          total: 0
        }
        methods.getMenuData()
      },
      clearForm() {
        state.menuForm = {
          type: 0,
          parentId: 0
        }
        menuRef.value.resetFields()
      },
      addMenu(row) {
        if (row) {
          state.isAddLower = true
          state.parentId = row.parentId
          state.menuForm.parentId = row.id
          state.visible = {
            isShow: true,
            type: 'add',
            title: row.name + ' - ' + '添加下级'
          }
        } else {
          state.isAddLower = false
          state.menuForm.parentId = 0
          state.parentId = 0
          state.visible = {
            isShow: true,
            type: 'add',
            title: '添加目录'
          }
        }

      },
      editMenu(row) {
        state.menuForm = {...row}
        state.parentId = row.parentId
        // state.cascaderData = methods.formatTree(state.tableAllData)
        state.isAddLower = true
        state.visible = {
          isShow: true,
          type: 'edit',
          title: row.name + ' - ' + '编辑菜单'
        }
      },
      checkChange(value) {
        state.menuForm.parentId = value[value.length - 1]
      },
      // 添加，编辑菜单
      menuConfirm() {
        menuRef.value.validate(async v => {
          if (v) {
            const isAdd = state.visible.type === 'add'
            const form = state.menuForm
            const url = ((form) => isAdd ? insertMenu(form) : updateMenu(form))
            const res = await url(form)
            if (res.code === 200) {
              state.visible.isShow = false
              ElMessage.success({
                message: isAdd ? '添加成功' : '编辑成功'
              })

              await methods.getMenuData()
              await methods.setUpDateTree()
            }
          }
        })
      },
      // 启用/禁用
      changeStatus(row) {
        ElMessageBox.confirm('确认进行此操作?', '提示', {
          type: 'warning',
        }).then(async () => {
          state.parentId = row.parentId
          const {id, status} = row
          const res = await changeMenuStatus({
            id, status: status === 0 ? 1 : 0
          })
          if (res.code === 200) {
            ElMessage.success({
              message: '操作成功'
            })
            await methods.getMenuData()
            await methods.setUpDateTree()
          }
        }).catch(() => {

        });
      },
      edlMenu({id, parentId}) {
        ElMessageBox.confirm('确认删除?', '提示', {
          type: 'warning',
        }).then(async () => {
          state.parentId = parentId
          const res = await deleteMenu({
            id,
          })
          if (res.code === 200) {
            ElMessage.success({
              message: '删除成功'
            })
            await methods.getMenuData()
            await methods.setUpDateTree()
          }
        }).catch(() => {

        });
      },
      // 格式化树
      formatTree: (list) => {
        return list.filter(father => {
          const childArr = list.filter(child => father.id === child.parentId)
          if (childArr.length > 0) {
            father.children = childArr.sort((a, b) => a.orderNum - b.orderNum)
          }
          return father.parentId === 0
        })
      }
    })
    onMounted(() => {
      methods.getMenuData()
    })
    return {
      tableColumn,
      menuRef,
      tableRef,
      menuType,
      ...toRefs(state),
      ...methods
    }
  }
})

</script>

<style scoped>

</style>
